﻿namespace IntellectShop.Common
{
	using System;
	using System.Collections.Generic;
	using System.IO;
	using System.Linq;
	using System.Net.Mail;
	using System.Text;
	using System.Text.RegularExpressions;

	public static class MailUtils
	{
		public static void Send(string from, string to, string templateFile, string encoding, string body, string username, string forceUsePickupDirectory, string blindCarbonCopy)
		{
			List<string> emailsTo = GetEmals(to);
			emailsTo.AddRange(GetEmals(blindCarbonCopy));

			if (emailsTo.Count == 0)
			{
				throw new Exception("Не задан получатель письма!");
			}

			using (MailMessage message = new MailMessage(new MailAddress(from), new MailAddress(emailsTo.First())))
			{
				foreach (string mail in emailsTo.Skip(1))
				{
					message.Bcc.Add(new MailAddress(mail));
				}

				InitMessage(message, "Уведомление",
					AlternateView.CreateAlternateViewFromString("Это автоматически генерируемое письмо.", null, "text/plain"),
					CreateHtmlViewFromTemplate(templateFile, encoding, body, username));
				SendMessage(message, forceUsePickupDirectory);
			}
		}

		public static List<string> GetEmals(string emails)
		{
			List<string> result = new List<string>();
			if (!String.IsNullOrEmpty(emails))
			{
				foreach (string mail in emails.Split(','))
				{
					if (String.IsNullOrEmpty(mail))
						continue;

					result.Add(mail.Trim());
				}
			}

			return result;
		}

		private static void SendMessage(MailMessage message, string forceUsePickupDirectory)
		{
			//Начинаем отправку сообщения
			SmtpClient smtpClient = new SmtpClient();
			if (!String.IsNullOrEmpty(forceUsePickupDirectory))
			{
				smtpClient.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;
				smtpClient.PickupDirectoryLocation = forceUsePickupDirectory;
			}

			smtpClient.EnableSsl = smtpClient.DeliveryMethod == SmtpDeliveryMethod.Network;
			try
			{
				smtpClient.Send(message);
			}
			catch (System.Net.Mail.SmtpException se)
			{
				if (smtpClient.EnableSsl)
				{
					//попробуем отправить с выключенным ssl
					smtpClient.EnableSsl = false;
					smtpClient.Send(message);
				}
				else
				{
					throw se;
				}
			}
		}

		private static void InitMessage(
			MailMessage message,
			string subject,
			AlternateView plainView,
			AlternateView htmlView)
		{
			//Формируем содержимое письма
			message.Subject = subject;
			message.DeliveryNotificationOptions =
				DeliveryNotificationOptions.OnFailure |
				DeliveryNotificationOptions.OnSuccess |
				DeliveryNotificationOptions.Delay;

			message.AlternateViews.Add(plainView);
			message.AlternateViews.Add(htmlView);
			message.IsBodyHtml = true;
			//письмо сформировано
		}

		private static AlternateView CreateHtmlViewFromTemplate(string templatePath, string encodingName, string body, string username)
		{
			List<string> imgUriList = new List<string>();

			Regex findImgSrc = new Regex(
					"(?<=img\\s+src\\=[\\x27\\x22])(?<imgUri>[^\\x27\\x22]*)(?=[\\x27\\x22])",
					RegexOptions.Compiled | RegexOptions.IgnoreCase
					);

			FileInfo fileInfo = new FileInfo(templatePath);
			StringBuilder buffer = new StringBuilder();

			using (StreamReader sr = new StreamReader(fileInfo.OpenRead(), GetEncoding(encodingName)))
			{
				String line = String.Empty;
				while ((line = sr.ReadLine()) != null)
				{
					foreach (Match match in findImgSrc.Matches(line))
					{
						string imgUri = match.Groups["imgUri"].Value;
						if (!String.IsNullOrEmpty(imgUri))
						{
							imgUriList.Add(imgUri);
						}

						line = line.Replace(imgUri, String.Format("cid:{0}", Path.GetFileNameWithoutExtension(imgUri)));
					}

					line = line.Replace("[username]", String.Format("{0}", username));
					line = line.Replace("[body]", String.Format("{0}", body));
					buffer.Append(line);
				}
			}

			AlternateView htmlView = AlternateView.CreateAlternateViewFromString(
					buffer.ToString(),
					null,
					"text/html");

			LinkedResource logo = null;
			foreach (string imgUri in imgUriList)
			{
				if (String.IsNullOrEmpty(imgUri))
				{
					continue;
				}

				try
				{
					logo = new LinkedResource(imgUri);
				}
				catch (FileNotFoundException)
				{
					logo = new LinkedResource(Path.Combine(Path.GetDirectoryName(templatePath), imgUri));
				}

				logo.ContentId = Path.GetFileNameWithoutExtension(imgUri);
				logo.ContentType.MediaType = "image/jpeg";
				logo.ContentType.Name = Path.GetFileName(imgUri);
				htmlView.LinkedResources.Add(logo);
			}

			return htmlView;
		}

		private static Encoding GetEncoding(string encodingName)
		{
			Encoding result = Encoding.Default;
			if (!String.IsNullOrEmpty(encodingName))
			{
				result = Encoding.GetEncoding(encodingName);
			}

			return result;
		}
	}
}
